﻿using System;
using System.Collections.Generic;
using System.Linq;
using Gumini.JulaDB.Expressions;
using Gumini.JulaDB.Planner;

namespace Gumini.JulaDB.Optimizer
{
    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    internal class InnerJoinClause
    {
        public InnerJoinClause(PlanNode left, PlanNode right, ColumnPair columnPair)
            : this(left, right, new[] { columnPair }) { }

        public InnerJoinClause(PlanNode left, PlanNode right, IEnumerable<ColumnPair> columnPairs)
        {
            if (columnPairs == null || !columnPairs.Any())
                throw new ArgumentException("columnPairs");

            if (left == null)
                throw new ArgumentNullException("left");
            if (right == null)
                throw new ArgumentNullException("right");

            this.LeftNode = left;
            this.RightNode = right;
            this.ColumnPairs = new List<ColumnPair>(columnPairs);
        }

        public PlanNode LeftNode { get; set; }

        public PlanNode RightNode { get; set; }

        public List<ColumnPair> ColumnPairs { get; set; }

        public InnerJoinClause GetReversedClause()
        {
            return new InnerJoinClause(
                left: this.RightNode,
                right: this.LeftNode,
                columnPairs: this.ColumnPairs.Select(p => p.GetReversedPair()));
        }

        public Expression GetEquivalentExpression()
        {
            var equalsExpressions = new List<BinaryExpression>();
            foreach (var pair in this.ColumnPairs)
            {
                equalsExpressions.Add(
                    new BinaryExpression(
                        op: "=",
                        left: pair.Left,
                        right: pair.Right));
            }
            Expression result = equalsExpressions.First();
            foreach (var expr in equalsExpressions.Skip(1))
            {
                result = new BinaryExpression(
                    op: "AND",
                    left: result,
                    right: expr);
            }
            return result;
        }

        public override string ToString()
        {
            return String.Join(", ", this.ColumnPairs);
        }
    }
}
